import "@babylonjs/core/Debug/debugLayer";
import "@babylonjs/inspector";
import {
    Engine,
    Scene,
    ArcRotateCamera,
    Vector3,
    HemisphericLight,
    MeshBuilder,
    HavokPlugin,
    PhysicsAggregate,
    PhysicsShapeType
} from "@babylonjs/core";
import HavokPhysics from "@babylonjs/havok";

(async function initApp() {
    var app = document.getElementById("app")!;
    app.style.width = "100vw";
    app.style.height = "100vh";
    app.style.overflow = "hidden";
    var canvas = document.createElement("canvas");
    canvas.style.width = "100%";
    canvas.style.height = "100%";
    canvas.id = "gameCanvas";
    app.appendChild(canvas);

    // initialize babylon scene and engine
    var engine = new Engine(canvas, true);
    var scene = new Scene(engine);

    var camera: ArcRotateCamera = new ArcRotateCamera(
        "Camera",
        Math.PI / 4,
        Math.PI / 4,
        10,
        Vector3.Zero(),
        scene
    );
    camera.attachControl(canvas, true);
    new HemisphericLight("light1", new Vector3(1, 1, 0), scene);

    // 球体和地面
    const ground = MeshBuilder.CreateGround("ground", { width: 10, height: 10 }, scene);
    const sphere = MeshBuilder.CreateSphere("sphere", { diameter: 1 }, scene);
    const sphere2 = MeshBuilder.CreateSphere("sphere2", { diameter: 1 }, scene);
    const sphere3 = MeshBuilder.CreateSphere("sphere3", { diameter: 1 }, scene);
    const sphere4 = MeshBuilder.CreateSphere("sphere4", { diameter: 1 }, scene);

    sphere.position.y = 0.5;
    sphere2.position.y = 1.5;
    sphere3.position.y = 2.5;
    sphere4.position.y = 7;

    // 启用物理引擎
    const gravityVector = new Vector3(0, -9.81, 0);
    const havokInstance = await HavokPhysics({
        locateFile: () => {
            return "./HavokPhysics.wasm";
        }
    });
    const physicsPlugin = new HavokPlugin(true, havokInstance);
    // 这里 gravityVector、physicsPlugin 都是可选参数
    // 默认就是 Vector3(0, -9.81, 0) 和 new HavokPlugin()
    scene.enablePhysics(gravityVector, physicsPlugin);

    const sphereAggregate = new PhysicsAggregate(
        sphere,
        PhysicsShapeType.SPHERE,
        { mass: 1, restitution: 1 },
        // { mass: 1, restitution: 0.75 },
        scene
    );
    const sphereAggregate2 = new PhysicsAggregate(
        sphere2,
        PhysicsShapeType.SPHERE,
        { mass: 1, restitution: 1 },
        // { mass: 1, restitution: 0.75 },
        scene
    );
    const sphereAggregate3 = new PhysicsAggregate(
        sphere3,
        PhysicsShapeType.SPHERE,
        { mass: 1, restitution: 1 },
        // { mass: 1, restitution: 0.75 },
        scene
    );
    const sphereAggregate4 = new PhysicsAggregate(
        sphere4,
        PhysicsShapeType.SPHERE,
        { mass: 1, restitution: 1 },
        // { mass: 1, restitution: 0.75 },
        scene
    );
    const groundAggregate = new PhysicsAggregate(ground, PhysicsShapeType.BOX, { mass: 0 }, scene);

    // hide/show the Inspector
    window.addEventListener("keydown", (ev) => {
        // Shift+Ctrl+Alt+I
        if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
            if (scene.debugLayer.isVisible()) {
                scene.debugLayer.hide();
            } else {
                scene.debugLayer.show();
            }
        }
    });

    // run the main render loop
    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", function () {
        engine.resize();
    });
})();